﻿using ezCloud.Api.Common;
using ezCloud.Api.Models;
using ezCloud.Data;
using Microsoft.AspNet.Identity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Threading.Tasks;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;
using Microsoft.Ajax.Utilities;
namespace ezCloud.Api.Controllers
{
    [ApiAuthorize]
    [RoutePrefix("api/CityLedger")]
    public class CityLedgerController : ApiController
    {
        private Common.MemoryCacher memCache = new Common.MemoryCacher();
        public CityLedgerController()
        {
        }
        public class SearchCityLedgerModel
        {
            public int? CompanyId { get; set; }
            public DateTime? From { get; set; }
            public DateTime? To { get; set; }
        }
        [HttpGet]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("GetDataInit")]
        public async Task<IHttpActionResult> DataInit()
        {
            var context = new ezCloudDataContext();
            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            if (currentHotel == null) return Ok();
            var company = context.Company.Where(c => c.HotelId == user.HotelId && c.IsAvailable == true).ToList();
            var currencies = context.Money.Where(curr => curr.HotelId == user.HotelId).ToList();
            var defaultCurrency = currencies.Where(cur => cur.MoneyId == currentHotel.DefaultMoneyId).FirstOrDefault();
            var DataInit = new
            {
                Companys = company,
                GeneralInfo = new
                {
                    PaymentMethods = context.PaymentMethods.Where(p => p.PaymentMethodName == "CASH" || p.PaymentMethodName == "BANK_TRANSFER").ToList(),
                    Money = context.Money.Where(m => m.HotelId == user.HotelId).ToList(),
                    DefaultHotelMoneyId = context.Hotels.Where(h => h.HotelId == user.HotelId).FirstOrDefault().DefaultMoneyId,
                    CurrenciesISO = context.Currencies,
                    defaultCurrency= defaultCurrency,
                    currencies= currencies
                },
            };
            //memCache.AddByHotelId(user.HotelId, "ROOMRESERVATION_" + reservationRoomId, ReservationRoom, DateTimeOffset.UtcNow.AddMinutes(5));
            return Ok(DataInit);
        }
      
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("processSearch")]
        public async Task<IHttpActionResult> processSearch(SearchCityLedgerModel model)
        {
            var context = new ezCloudDataContext();
            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            var timeZoneOffset = -currentHotel.TimeZoneOffset / 60;
            TimeSpan offSet = new TimeSpan(timeZoneOffset, 0, 0);
          
            if (model.From == null)
            {
                model.From = ((DateTime)SqlDateTime.MinValue).Date;
            }
            else
            {
                DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.From).Year, ((DateTime)model.From).Month, ((DateTime)model.From).Day, ((DateTime)model.From).Hour, ((DateTime)model.From).Minute, ((DateTime)model.From).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.ReservationFrom = fromTemp.Date;
                DateTime from = (DateTime)fromTemp.Date;
                from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                model.From = from;
            }

            if (model.To == null)
            {
                model.To = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            else
            {
                DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.To).Year, ((DateTime)model.To).Month, ((DateTime)model.To).Day, ((DateTime)model.To).Hour, ((DateTime)model.To).Minute, ((DateTime)model.To).Second, offSet).ToOffset(TimeSpan.Zero);
                DateTime to = (DateTime)toTemp.Date;
                to = to.AddDays(1);
                model.To = to;
            }
            double totalBalanceBefore = 0;
            List<Staffs> listUser = context.Staffs.Where(s => s.HotelId == user.HotelId).ToList();
            string hotelOwnerId = context.Hotels.Where(h => h.HotelId == user.HotelId).FirstOrDefault().HotelOwnerId;
            var userOwner = context.AspNetUsers.Where(u => u.Id == hotelOwnerId).FirstOrDefault();
            listUser.Add(
                new Staffs()
                {
                    Email = userOwner.Email,
                    UserId = hotelOwnerId
                });
            var paymentListBalanceBefore = context.Payments.Where(p => p.HotelId == user.HotelId && p.CreatedDate <= model.From && p.CompanyId == model.CompanyId && p.RefPaymentId == null

                                                     ).Select(
                                                            s => new
                                                            {
                                                                s.CreatedDate,
                                                                s.PaymentMethods.PaymentMethodName,
                                                                Credit = s.PaymentMethods.PaymentMethodName != "CITY_LEDGER" ? s.Amount : 0,
                                                                Debit = s.PaymentMethods.PaymentMethodName == "CITY_LEDGER" ? s.Amount : 0
                                                            }
                                                        ).ToList();

            if (paymentListBalanceBefore.Count > 0) totalBalanceBefore =(double)paymentListBalanceBefore.Sum(c => c.Debit - c.Credit);
            var paymentList = context.Payments.Where(p => p.HotelId == user.HotelId
                                                    && p.CompanyId==model.CompanyId    
                                                    && ((p.PaymentMethods.PaymentMethodName == "CITY_LEDGER" && p.RefPaymentId == null)
                                                        ||
                                                        (p.ReservationRoomId == null )
                                                        )
                                                    && p.CreatedDate>model.From && p.CreatedDate<model.To
                                                    )
                                                    .Select(
                                                      s => new
                                                      {
                                                          s.HotelId,
                                                          s.PaymentId,
                                                          s.PaymentNumber,
                                                          s.CreatedDate,
                                                          s.CreatedUserId,
                                                          s.PaymentDescription,
                                                          s.ReservationRooms.Travellers.Fullname,
                                                          s.PaymentMethods.PaymentMethodName,
                                                          s.ReservationRooms.Reservations.ReservationNumber,
                                                          s.ReservationRooms.Rooms.RoomName,
                                                          s.Amount,
                                                          s.RefPaymentId,
                                                          s.AmountInSpecificMoney,
                                                          s.CompanyId,
                                                          s.MoneyId,
                                                          s.Money.MoneyName,
                                                          s.PaymentMethodId
                                                      }

                                                    )
                                                    .OrderBy(o => o.CreatedDate).ToList();

            var hotelInvoiceQuery = context.HotelForm.Where(hf => hf.HotelId == user.HotelId);
            var result = new
            {   
                GeneralInfo = new
                {
                    PaymentMethods = context.PaymentMethods.Where(p => p.PaymentMethodName == "CASH" || p.PaymentMethodName == "BANK_TRANSFER").ToList(),
                    Money = context.Money.Where(m => m.HotelId == user.HotelId).ToList(),
                    DefaultHotelMoneyId = context.Hotels.Where(h => h.HotelId == user.HotelId).FirstOrDefault().DefaultMoneyId,
                    CurrenciesISO = context.Currencies,
                },
                paymentListBalanceBefore = paymentListBalanceBefore,
                paymentList = paymentList,
                totalBalanceBefore= totalBalanceBefore,
                listUser,
                hotelFormRoomReceipt = context.HotelForm.Where(hf =>hf.HotelId==user.HotelId && hf.FormType == "Receipt").FirstOrDefault()
        };
            //memCache.AddByHotelId(user.HotelId, "ROOMRESERVATION_" + reservationRoomId, ReservationRoom, DateTimeOffset.UtcNow.AddMinutes(5));
            return Ok(result);
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("DeletePayment")]
        public async Task<IHttpActionResult> PostDeletePayment(PaymentModel payments)
        {
            var user = Common.UserUtitily.getUserProfile();
            var payment = payments.payment;
            var context = new ezCloudDataContext();
            var oldPayment = context.Payments.Where(p => p.HotelId == user.HotelId && p.PaymentId == payment.PaymentId).FirstOrDefault();
            if (oldPayment == null)
            {
                return BadRequest("Payment does not exist!");
            }
            else
            {


                Payments deletedPayment = new Payments();

                deletedPayment = payment;
                deletedPayment.PaymentDescription = payment.PaymentDescription;
                deletedPayment.Amount = (payment.PaymentTypeName == "REFUND") ? payment.Amount : -payment.Amount;
                deletedPayment.CreatedDate = DateTime.UtcNow;
                deletedPayment.PaymentTypeName = "DELETED";
                deletedPayment.CreatedUserId = user.UserId;
                // deletedPayment.RefPaymentId = null;

                context.Payments.InsertOnSubmit(deletedPayment);
                context.SubmitChanges();
                Common.Elastic.IndexLastAudit(context);
                oldPayment.RefPaymentId = deletedPayment.PaymentId;

                Notification.processNotificationDeleteCityLedgerPayment(payments, user);
                context.SubmitChanges();
                Common.Elastic.IndexLastAudit(context);
               
            }
         
            return Ok();
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("AddPayment")]
        public async Task<IHttpActionResult> AddPayment(PaymentModel payments)
        {
            var user = Common.UserUtitily.getUserProfile();
            var payment = payments.payment;
            var context = new ezCloudDataContext();
            payment.HotelId = user.HotelId;
            //payment.CreatedDate = DateTime.UtcNow;
            payment.CreatedUserId = user.UserId;

            if (payment.PaymentTypeName != "DELETED" || payment.RefPaymentId == null)
            {
                payment.PaymentNumber = InvoiceNumberGenerator.getInvoiceNumber(user.HotelId, payment.PaymentTypeName);

                Notification.processNotificationAddNewCityLedgerPayment(payments, user);

                context.Payments.InsertOnSubmit(payment);
            }

            //Notification.sendNotificationToDevice(user.UserName.ToLower(), user.FullName + " Checkin " + context.Rooms.Where(R => R.HotelId == user.HotelId && R.RoomId == oldRR.RoomId).FirstOrDefault().RoomName, user.HotelId, "NOTIFICATION_CHECKEDIN");

            context.SubmitChanges();
            Common.Elastic.IndexLastAudit(context);
            return Ok();
        }
    }
}